{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Cython：Typed memoryviews"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 例子"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里 `double[::1]` 是一种 `memoryview` 方法，效率跟 `Numpy` 数组差不多，可以给 `C` 数组赋值，可以给 `Numpy` 数组赋值，可以像 `Numpy` 一样切片："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Writing cython_sum.pyx\n"
     ]
    }
   ],
   "source": [
    "%%file cython_sum.pyx\n",
    "def cython_sum(double[::1] a):\n",
    "    cdef double s = 0.0\n",
    "    cdef int i, n = a.shape[0]\n",
    "    for i in range(n):\n",
    "        s += a[i]\n",
    "    return s"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Writing setup.py\n"
     ]
    }
   ],
   "source": [
    "%%file setup.py\n",
    "from distutils.core import setup\n",
    "from distutils.extension import Extension\n",
    "from Cython.Distutils import build_ext\n",
    "\n",
    "ext = Extension(\"cython_sum\", [\"cython_sum.pyx\"])\n",
    "\n",
    "setup(\n",
    "    cmdclass = {'build_ext': build_ext},\n",
    "    ext_modules = [ext],\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "running build_ext\n",
      "cythoning cython_sum.pyx to cython_sum.c\n",
      "building 'cython_sum' extension\n",
      "creating build\n",
      "creating build\\temp.win-amd64-2.7\n",
      "creating build\\temp.win-amd64-2.7\\Release\n",
      "C:\\Anaconda\\Scripts\\gcc.bat -DMS_WIN64 -mdll -O -Wall -IC:\\Anaconda\\include -IC:\\Anaconda\\PC -c cython_sum.c -o build\\temp.win-amd64-2.7\\Release\\cython_sum.o\n",
      "writing build\\temp.win-amd64-2.7\\Release\\cython_sum.def\n",
      "C:\\Anaconda\\Scripts\\gcc.bat -DMS_WIN64 -shared -s build\\temp.win-amd64-2.7\\Release\\cython_sum.o build\\temp.win-amd64-2.7\\Release\\cython_sum.def -LC:\\Anaconda\\libs -LC:\\Anaconda\\PCbuild\\amd64 -lpython27 -lmsvcr90 -o \"C:\\Users\\lijin\\Documents\\Git\\python-tutorial\\07. interfacing with other languages\\cython_sum.pyd\"\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "cython_sum.c: In function '__Pyx_BufFmt_ProcessTypeChunk':\n",
      "cython_sum.c:13561:26: warning: unknown conversion type character 'z' in format [-Wformat]\n",
      "cython_sum.c:13561:26: warning: unknown conversion type character 'z' in format [-Wformat]\n",
      "cython_sum.c:13561:26: warning: too many arguments for format [-Wformat-extra-args]\n",
      "cython_sum.c:13613:20: warning: unknown conversion type character 'z' in format [-Wformat]\n",
      "cython_sum.c:13613:20: warning: unknown conversion type character 'z' in format [-Wformat]\n",
      "cython_sum.c:13613:20: warning: too many arguments for format [-Wformat-extra-args]\n",
      "cython_sum.c: In function '__pyx_buffmt_parse_array':\n",
      "cython_sum.c:13675:25: warning: unknown conversion type character 'z' in format [-Wformat]\n",
      "cython_sum.c:13675:25: warning: format '%d' expects argument of type 'int', but argument 3 has type 'size_t' [-Wformat]\n",
      "cython_sum.c:13675:25: warning: too many arguments for format [-Wformat-extra-args]\n",
      "cython_sum.c: In function '__Pyx_GetBufferAndValidate':\n",
      "cython_sum.c:13860:7: warning: unknown conversion type character 'z' in format [-Wformat]\n",
      "cython_sum.c:13860:7: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'Py_ssize_t' [-Wformat]\n",
      "cython_sum.c:13860:7: warning: unknown conversion type character 'z' in format [-Wformat]\n",
      "cython_sum.c:13860:7: warning: too many arguments for format [-Wformat-extra-args]\n",
      "cython_sum.c: In function '__Pyx_RaiseArgtupleInvalid':\n",
      "cython_sum.c:14032:18: warning: unknown conversion type character 'z' in format [-Wformat]\n",
      "cython_sum.c:14032:18: warning: format '%s' expects argument of type 'char *', but argument 5 has type 'Py_ssize_t' [-Wformat]\n",
      "cython_sum.c:14032:18: warning: unknown conversion type character 'z' in format [-Wformat]\n",
      "cython_sum.c:14032:18: warning: too many arguments for format [-Wformat-extra-args]\n",
      "cython_sum.c: In function '__Pyx_RaiseTooManyValuesError':\n",
      "cython_sum.c:14552:18: warning: unknown conversion type character 'z' in format [-Wformat]\n",
      "cython_sum.c:14552:18: warning: too many arguments for format [-Wformat-extra-args]\n",
      "cython_sum.c: In function '__Pyx_RaiseNeedMoreValuesError':\n",
      "cython_sum.c:14558:18: warning: unknown conversion type character 'z' in format [-Wformat]\n",
      "cython_sum.c:14558:18: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'Py_ssize_t' [-Wformat]\n",
      "cython_sum.c:14558:18: warning: too many arguments for format [-Wformat-extra-args]\n",
      "cython_sum.c: In function '__Pyx_ValidateAndInit_memviewslice':\n",
      "cython_sum.c:15253:22: warning: unknown conversion type character 'z' in format [-Wformat]\n",
      "cython_sum.c:15253:22: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'Py_ssize_t' [-Wformat]\n",
      "cython_sum.c:15253:22: warning: unknown conversion type character 'z' in format [-Wformat]\n",
      "cython_sum.c:15253:22: warning: too many arguments for format [-Wformat-extra-args]\n"
     ]
    }
   ],
   "source": [
    "!python setup.py build_ext -i"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from cython_sum import cython_sum\n",
    "from numpy import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "a = arange(1e6)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "检查正确性："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "499999500000.0"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cython_sum(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "499999500000.0"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.sum()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "效率："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "100 loops, best of 3: 2.14 ms per loop\n"
     ]
    }
   ],
   "source": [
    "%timeit cython_sum(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "100 loops, best of 3: 2.38 ms per loop\n"
     ]
    }
   ],
   "source": [
    "%timeit a.sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import zipfile\n",
    "\n",
    "f = zipfile.ZipFile('07-06-cython-sum.zip','w',zipfile.ZIP_DEFLATED)\n",
    "\n",
    "names = ['cython_sum.pyx',\n",
    "         'setup.py']\n",
    "for name in names:\n",
    "    f.write(name)\n",
    "\n",
    "f.close()\n",
    "\n",
    "!rm -f setup*.*\n",
    "!rm -f cython_sum*.*\n",
    "!rm -rf build"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
